package com.beiding.starter;

import com.beiding.hotcode.*;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.nio.charset.Charset;
import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.Map;


public class Starter {

    private static Instrumentation inst;

    public static MyFactory factory;
    public static String encoding;

    private static ClassGroup classGroup;

    //TODO 在改变属性的时候并不会触发检查操作

    //TODO 使用启动参数指定源码路径以及编码字符集  然后对源码路径下的java文件进行类代理,在调用其任意方法时触发检查
    public static void premain(String agentArgs, Instrumentation inst) {

        if (agentArgs == null) {
            throw new RuntimeException("未指定任何启动参数");
        }

        String[] split = agentArgs.split(",");

        if (split.length == 0) {
            throw new RuntimeException("未指定任何启动参数");
        }

        Map<String, String> params = new HashMap<>();

        for (String s : split) {
            String[] strings = s.split(" +");
            if (strings.length > 2 || strings.length == 0) {
                throw new RuntimeException("无效参数:" + s);
            }

            if (strings.length == 2) {
                params.put(strings[0], strings[1]);
            } else {
                params.put(strings[0], "");
            }

        }

        String src = params.get("src");
        if (src == null) {
            throw new RuntimeException("未指定源码路径");
        }

        File srcRoot = new File(src);

        if (!srcRoot.exists() || !srcRoot.isDirectory()) {
            throw new RuntimeException(srcRoot.getAbsolutePath() + " 不是有效的路径");
        }

        HotCodeConfig hotCodeConfig = new HotCodeConfig();

        hotCodeConfig.srcRoot(srcRoot.getAbsolutePath());

        String encoding = params.get("encoding");

        if (encoding != null) {
            hotCodeConfig.encoding(encoding);
        }

        Starter.encoding = hotCodeConfig.getEncoding();

        //构建工厂
        factory = new MyFactory(hotCodeConfig);

        //所有使用工厂创建出来的类都添加同一个类组中
        classGroup = factory.createClassGroup();


    }


    //TODO 如果是热编译路径下的文件就动态代理
    private static class MyClassFileTransformer implements ClassFileTransformer {
        @Override
        public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

            className = className.replace("/", ".");
            MyClass myClass = factory.getMyClass(className);

            //如果这个类存在
            if (myClass == null) {
                return null;
            }

            JavaCompiler cmp = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager fileManager = cmp.getStandardFileManager(null, null, Charset.forName(encoding));

            //然后进行编译操作

        }
    }

    private static File writeToJavaFile(String text) {

        try {
            File file = File.createTempFile("hotcode-", ".java");
            FileWriter fileWriter = new FileWriter(file);
            fileWriter.write(text);
            fileWriter.close();
            return file;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }


    }


    private static class M {

        private static final MyClass myClass = factory.getMyClass("");

        private MyInstance myInstance;

        //同名的构造函数
        M() {
            myInstance = myClass.newInstance();
        }

    }


}
